﻿/**********************************************/
/*Project: CRF#                               */
/*Author: Zhongkai Fu                         */
/*Email: fuzhongkai@gmail.com                 */
/**********************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace CRFSharp
{
    public class CrfModel
    {
        uint maxid_;  //alpha数组的最大ID
        List<int> alpha_int_;  //alpha数组
        double cost_factor_; //计算cost时的相乘因子
        uint xsize_;  //特征size 
        List<string> unigram_templs_;
        List<string> bigram_templs_;
       
        string [] y_; //类别字符表示数组
        int model_init_stat;

        public uint version; //模型版本号,读取模型时读入
        public Trie trie; //查找特征对应ID

        public CrfModel()
        {
            maxid_ = 0;
            alpha_int_ = null;
            cost_factor_ = 1.0;
            xsize_ = 0;
            unigram_templs_ = null;
            bigram_templs_ = null;
            model_init_stat = Utils.MODEL_INIT_UNFINISH;
        }

        //获取maxid_
        public uint size() { return maxid_; }
       
        //获取类别个数
        public uint ysize() { return (uint)y_.Length; }

        public uint xsize()
        {
            return (uint)xsize_;
        }

        //获取类别i的字符表示
        public string y(int i) { return y_[i]; }

        //获取alpha数组地址(int类型)
        public List<int> alpha_int()
        {
            return alpha_int_;
        }
      
        //获取cost factor
        public double cost_factor() { return cost_factor_; }

        //获取key对应的特征id
        public int get_id(string str)
        {
            int data = -1;
            bool ret;
            ret = trie.Match(str, out data);
            if (ret == false)
            {
                return -1;
            }
            else
            {
                return data;
            }
        }

        //获取unigram模板指针
        public List<string> get_unigram_templs()
        {
            return unigram_templs_;
        }

        public List<string> get_bigram_templs()
        {
            return bigram_templs_;
        }
       
        //获取模型初始化状态
        //返回MODEL_INIT_STAT_FINISH为初始化完成，返回MODEL_INIT_STAT_UNFINISH为初始化未完成
        public int get_model_init_stat()
        {
            return model_init_stat;
        }

        //加载model文件
        //返回值<0 为出错，=0为正常
        public int load_model(string filename)
        {
            StreamReader sr = new StreamReader(filename);
            string strLine;

           
            //读入版本号
            //version: 100
            strLine = sr.ReadLine();
            version = uint.Parse( strLine.Split(':')[1].Trim());

            //读入cost_factor
            strLine = sr.ReadLine();
            cost_factor_ = double.Parse(strLine.Split(':')[1].Trim());


            //读入maxid
            strLine = sr.ReadLine();
            maxid_ = uint.Parse(strLine.Split(':')[1].Trim());

            //读入xsize
            strLine = sr.ReadLine();
            xsize_ = uint.Parse(strLine.Split(':')[1].Trim());


            //读入空行
            strLine = sr.ReadLine();

            //读入待标注的标签
            List<string> yList = new List<string>();
            while (true)
            {
                strLine = sr.ReadLine();
                if (strLine.Length == 0)
                {
                    break;
                }
                yList.Add(strLine);
            }
            y_ = yList.ToArray();


            //读入unigram和bigram模板
            unigram_templs_ = new List<string>();
            bigram_templs_ = new List<string>();
            while (true)
            {
                strLine = sr.ReadLine();
                if (strLine.Length == 0)
                {
                    break;
                }
                if (strLine[0] == 'U')
                {
                    unigram_templs_.Add(strLine);
                }
                if (strLine[0] == 'B')
                {
                    bigram_templs_.Add(strLine);
                }
            }

            //将[ID, feature]读入TrieTree
            trie = new Trie();
            Dictionary<string, int> feature2id = new Dictionary<string, int>();
            while (true)
            {
                strLine = sr.ReadLine();
                if (strLine.Length == 0)
                {
                    break;
                }

                string[] items = strLine.Split(' ');
                feature2id.Add(items[1], int.Parse(items[0]));
            }
            trie.Build(ref feature2id);
           

            //alpha数组，从float转为int，乘CONV_INT_FACTOR
            alpha_int_ = new List<int>((int)(maxid_ + 1));
            int conv_alpha_int;
            for (int i = 0; i < maxid_; i++)
            {
                float alpha_float;
                alpha_float = float.Parse(sr.ReadLine());
                conv_alpha_int = (int)(alpha_float * Utils.CONV_INT_FACTOR);
                alpha_int_.Add(conv_alpha_int);
            }

            if (sr.EndOfStream == false)
            {
                sr.Close();
                return -1;
            }

            model_init_stat = Utils.MODEL_INIT_FINISH;

            sr.Close();
            return 0;
        }

    }
}
